<?php
/**
 * @author Martin Scotta <martinscotta@gmail.com>
 */

/**
 * @see Lite_Collection_Sequence
 */
class Lite_Collection_ArraySequence 
	extends Lite_Collection_AbstractCollection
	implements Lite_Collection_Sequence {

	/**
	 * @param LiteCollection $colA
	 * @param LiteCollection $colB
	 * 
	 * @return LiteCollection
	 */
	static function union(LiteCollection $colA, LiteCollection $colB) {
		return self::unionInto(new self, $colA, $colB);
	}
	
	/**
	 * Secuencia ordenada de elementos
	 * @var array
	 */
	private $sequence = array();
	
	/**
	 * @param int $index
	 * @param mixed $element
	 * @throws Lite_Exception_IndexOutOfBound
	 */
	public function addAt($index, $element){
		$this->throwIfInvalidIndex($index);
		$this->remove($element);
		array_splice($this->sequence, $index, 0, array($element) );
	}
	
	/**
	 * @param int $index
	 * @return mixed
	 * @throws Lite_Exception_IndexOutOfBound
	 */
	public function getAt($index){
		$this->throwIfInvalidIndex($index);
		return $this->sequence[$index];
	}

	/**
	 * @param unknown_type unknown_type unknown_type unknown_type $index
	 */
	public function removeAt($index){
		$this->throwIfInvalidIndex($index);
		array_splice($this->sequence, $index, 1);
	}

	/**
	 * @param unknown_type $element
	 */
	public function indexOf($element){
		$index = array_search($element, $this->sequence, true);
		return $index !== false ? $index : -1;
	}
	
	/**
	 * @param int $index
	 * @param string $message
	 */
	private function throwIfInvalidIndex($index) {
		if( $index < 0 || $index > $this->size() ) {
			throw new Lite_Exception_IndexOutOfBoundException("{$index} is not a valid position");
		}
	}
	
	/**
	 * 
	 */
	public function clear(){
		$this->sequence = array();
	}

	/**
	 * @param mixed $element
	 */
	public function add($element){
		$this->remove($element);
		$this->sequence[] = $element;
	}
	
	/**
	 * @param unknown_type $element
	 */
	public function contains($element){
		return $this->indexOf($element) != -1;
	}

	/**
	 * @param unknown_type $element
	 */
	public function remove($element){
		if( ($index = $this->indexOf($element)) != -1) {
			$this->removeAt($index);
		}
	}

	/**
	 * @return boolean
	 */
	public function isEmpty(){
		return empty( $this->sequence );
	}

	/**
	 * @return int 
	 */
	public function size(){
		return count( $this->sequence );
	}

	/**
	 * @return array
	 */
	public function toArray(){
		return $this->sequence;
	}
}